package com.zjsru.plan2023.oneday;

import java.util.ArrayDeque;
import java.util.Deque;

/**
 * @Author: cookLee
 * @Date: 2023-11-28
 * 设计前中后队列
 * 双端队列，分裂成两个队列来村粗，如果插入前面则插入左队列，如果插入末尾插入右队列，如果插入中间，则按照下述规则来进行插入
 */
public class FrontMiddleBackQueue {

    /**
     * 左队列：，并且左边尾部与右边头部相接
     */
    Deque<Integer> left;
    /**
     * 右侧
     */
    Deque<Integer> right;

    /**
     * 初始化前中后队列
     */
    public FrontMiddleBackQueue() {
        this.left = new ArrayDeque<Integer>();
        this.right = new ArrayDeque<Integer>();
    }

    /**
     * 放入首位
     * 在 left 的头部插入，若插入后 left 的长度比 right 的长度大 2，需要将 left 的尾部元素移动到 right 的头部
     *
     * @param val val
     */
    public void pushFront(int val) {
        this.left.offerFirst(val);
        if (this.left.size() == this.right.size() + 2) {
            this.right.offerFirst(this.left.pollLast());
        }
    }

    /**
     * 放入中位
     * 在 left 的尾部插入，若插入前 left 的长度比 right 的长度大 1，需要先把 left 的尾部元素移动到 right 的头部，然后再插入新元素
     *
     * @param val val
     */
    public void pushMiddle(int val) {
        if (this.left.size() == this.right.size() + 1) {
            this.right.offerFirst(this.left.pollLast());
        }
        this.left.offerLast(val);
    }

    /**
     * 放入末位
     * 在 right 尾部插入，若插入后 right 的长度比 left 的长度大 1，需要将 right 的头部元素移动到 left 的尾部
     * @param val val
     */
    public void pushBack(int val) {
        this.right.offerLast(val);
        if (this.left.size() + 1 == this.right.size()) {
            this.left.offerLast(this.right.pollFirst());
        }
    }

    /**
     * 移除首位
     * 删除 left 的头部元素，若删除后 left 的长度比 right 的长度小 1，需要将 right 的头部元素移动到 left 的尾部
     *
     * @return int
     */
    public int popFront() {
        if (this.left.isEmpty()) {
            return -1;
        }
        int val = this.left.pollFirst();
        if (this.left.size() + 1 == this.right.size()) {
            this.left.offerLast(this.right.pollFirst());
        }
        return val;
    }

    /**
     * 移除中位
     * 删除 left 的尾部元素，若删除后 left 的长度比 right 的长度小 1，需要将 right 的头部元素移动到 left的尾部
     *
     * @return int
     */
    public int popMiddle() {
        if (this.left.isEmpty()) {
            return -1;
        }
        int val = this.left.pollLast();
        if (this.left.size() + 1 == this.right.size()) {
            this.left.offerLast(this.right.pollFirst());
        }
        return val;
    }

    /**
     * 移除末位
     * 1.若 right 为空（此时队列中仅存在一个元素），删除 left 的尾部元素
     * 2.删除后 left 的长度比 right 的长度大 2，需要将 left 的尾部元素移动到 right 的头部。
     * @return int
     */
    public int popBack() {
        if (this.left.isEmpty()) {
            return -1;
        }
        int val = 0;
        if (this.right.isEmpty()) {
            val = left.pollLast();
        } else {
            val = this.right.pollLast();
            if (this.left.size() == this.right.size() + 2) {
                this.right.offerFirst(this.left.pollLast());
            }
        }
        return val;
    }

}
